package cn.hrfax.stf.sdk.util;

import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

/**
 * @author yongSen.wang
 * @date 2020/6/15 15:27
 */
@Slf4j
public class DES3Util {
    private static final String DEFAULT_SIGNATURE_ALGORITHM = "SHA1WithRSA";
    private static final String DEFAULT_CHARSET = "UTF-8";
    /**
     * 加密算法
     */
    private static final String DEFAULT_KEY_ALGORTHM = "RSA";

    /**
     * 加密方法-默认编码utf-8
     *
     * @param encryptString
     * @param encryptKey
     * @param iv
     * @return
     * @throws Exception
     */
    public static String defaultEncryptDES3(String encryptString, String encryptKey, String iv) throws Exception {
        return encryptDES3(encryptString, encryptKey, iv, DEFAULT_CHARSET);
    }

    /**
     * 解密方法-默认编码utf-8
     *
     * @param encryptText
     * @param seckey
     * @param iv
     * @return
     * @throws Exception
     */
    public static String defaultDecryptDES3(String encryptText, String seckey, String iv) throws Exception {
        return decryptDES3(encryptText, seckey, iv, DEFAULT_CHARSET);
    }

    /**
     * 加签默认方法
     *
     * @param content
     * @param privateKey
     * @return
     */
    public static String defaultSign(String content, String privateKey) {
        return sign(content, privateKey, DEFAULT_CHARSET, DEFAULT_KEY_ALGORTHM, DEFAULT_SIGNATURE_ALGORITHM);
    }

    public static boolean defaultVerify(String content, String sign, String publicKey) {
        return verify(content, sign, publicKey, DEFAULT_CHARSET, DEFAULT_KEY_ALGORTHM, DEFAULT_SIGNATURE_ALGORITHM);
    }

    /**
     * 加密方法
     *
     * @param encryptString
     * @param encryptKey
     * @param iv
     * @return
     * @throws Exception
     */
    public static String encryptDES3(String encryptString, String encryptKey, String iv, String charset) throws Exception {
        try {
            DESedeKeySpec spec = new DESedeKeySpec(encryptKey.getBytes(charset));
            SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
            Key deskey = keyfactory.generateSecret(spec);

            Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
            IvParameterSpec ips = new IvParameterSpec(iv.getBytes(charset));
            cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
            byte[] encryptData = cipher.doFinal(encryptString.getBytes(charset));
            return Base64.encodeBase64String(encryptData);
        } catch (Exception ex) {
            throw ex;
        }
    }

    /**
     * 解密方法
     *
     * @param encryptText
     * @param seckey
     * @param iv
     * @return
     * @throws Exception
     */
    public static String decryptDES3(String encryptText, String seckey, String iv, String charset) throws Exception {
        Key deskey;
        DESedeKeySpec spec = new DESedeKeySpec(seckey.getBytes(charset));
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        deskey = keyfactory.generateSecret(spec);
        Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
        IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, deskey, ips);

        byte[] decryptData = cipher.doFinal(Base64.decodeBase64(encryptText));
        return new String(decryptData, charset);
    }

    /**
     * 私钥签名
     *
     * @param content
     * @param privateKey
     * @param charset
     * @param keyAlgorthm
     * @param randomAlgorithm
     * @return
     */
    public static String sign(String content, String privateKey, String charset, String keyAlgorthm,
                              String randomAlgorithm) {
        try {
            //解密私钥
            byte[] keyBytes = Base64.decodeBase64(privateKey);
            //构造PKCS8EncodedKeySpec对象
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
            //指定加密算法
            KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorthm);

            PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Signature signature = Signature.getInstance(randomAlgorithm);
            signature.initSign(priKey);
            signature.update(content.getBytes(charset));
            byte[] signed = signature.sign();
            return Base64.encodeBase64String(signed);
        } catch (Exception e) {
            log.error("签名异常 exception", e);
        }
        return null;
    }
    /**
     * 公钥验签
     *
     * @param content
     * @param sign
     * @param publicKey
     * @param charset
     * @return
     */
    public static boolean verify(String content, String sign, String publicKey, String charset, String keyAlgorthm,
                                 String randomAlgorithm) {
        try {
            //解密公钥
            byte[] keyBytes = Base64.decodeBase64(publicKey);
            //构造X509EncodedKeySpec对象
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
            //指定加密算法
            KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorthm);
            //取公钥匙对象
            PublicKey pubKey = keyFactory.generatePublic(x509EncodedKeySpec);

            Signature signature = Signature.getInstance(randomAlgorithm);
            signature.initVerify(pubKey);
            signature.update(content.getBytes(charset));
            //验证签名是否正常
            return signature.verify(Base64.decodeBase64(sign));
        } catch (Exception e) {
            log.error("验签异常 exception", e);
        }
        return false;
    }

}